#include "serialport.h"
using namespace SerialPortInterface;

SerialPort::SerialPort(
		       Device device,
		       BaudRate _baudrate,
		       DataBits _databits,
		       StopBits _stopbits,
		       Parity _parity
		       ) {
  fd = open(device.c_str(), O_RDWR);
  this->device = device;
  
  tcgetattr(fd, &OldOptions);
  
  setBaudRate(_baudrate);
  setDataBits(_databits);
  setStopBits(_stopbits);
  setParity(_parity);
}

SerialPort::~SerialPort() {
  tcsetattr(fd, TCSANOW, &OldOptions);

  close(fd);
}

char SerialPort::getChar() {
  char buf[2];
  read(fd, buf, 1);

  return buf[0];
}

std::string SerialPort::getString(int length) {
  std::string str;

  for (int i=0; i<length; i++)
    str.push_back(getChar());

  return str;
}
    
void SerialPort::sendChar(char x) {
  char buf[2];
  buf[0] = x;
  buf[1] = '\0';

  write(fd, buf, 1);
}

void SerialPort::sendString(std::string str) {
  for (std::string::iterator i = str.begin(); i != str.end(); ++i)
    sendChar(*i);
}

void SerialPort::sendFile(std::string filename) {
  std::ifstream ifs(filename.c_str() );

  while ( ifs.good() ) 
    sendChar(ifs.get());
}

void SerialPort::setBaudRate(BaudRate BR) {
  baudrate = BR;

  struct termios options;
  tcgetattr(fd, &options);

  switch (baudrate) {
  case BaudRate50:
    cfsetispeed(&options, B50);
    cfsetospeed(&options, B50);
    break;
  case BaudRate75:
    cfsetispeed(&options, B75);
    cfsetospeed(&options, B75);
    break;
  case BaudRate110:
    cfsetispeed(&options, B110);
    cfsetospeed(&options, B110);
    break;
  case BaudRate134:
    cfsetispeed(&options, B134);
    cfsetospeed(&options, B134);
    break;
  case BaudRate150:
    cfsetispeed(&options, B150);
    cfsetospeed(&options, B150);
    break;
  case BaudRate200:
    cfsetispeed(&options, B200);
    cfsetospeed(&options, B200);
    break;
  case BaudRate300:
    cfsetispeed(&options, B300);
    cfsetospeed(&options, B300);
    break;
  case BaudRate600:
    cfsetispeed(&options, B600);
    cfsetospeed(&options, B600);
    break;
  case BaudRate1200:
    cfsetispeed(&options, B1200);
    cfsetospeed(&options, B1200);
    break;
  case BaudRate1800:
    cfsetispeed(&options, B1800);
    cfsetospeed(&options, B1800);
    break;
  case BaudRate2400:
    cfsetispeed(&options, B2400);
    cfsetospeed(&options, B2400);
    break;
  case BaudRate4800:
    cfsetispeed(&options, B4800);
    cfsetospeed(&options, B4800);
    break;
  case BaudRate9600:
    cfsetispeed(&options, B9600);
    cfsetospeed(&options, B9600);
    break;
  case BaudRate19200:
    cfsetispeed(&options, B19200);
    cfsetospeed(&options, B19200);
    break;
  case BaudRate38400:
    cfsetispeed(&options, B38400);
    cfsetospeed(&options, B38400);
    break;
  case BaudRate57600:
    cfsetispeed(&options, B57600);
    cfsetospeed(&options, B57600);
    break;
  case BaudRate115200:
    cfsetispeed(&options, B115200);
    cfsetospeed(&options, B115200);
    break;
  }

  tcsetattr(fd, TCSANOW, &options);
}

void SerialPort::setDataBits(DataBits DB) {
  databits = DB;

  struct termios options;
  tcgetattr(fd, &options);

  options.c_cflag &= ~CSIZE;

  switch (databits) {
  case DataBits5:
    options.c_cflag |= CS5;
    break;
  case DataBits6:
    options.c_cflag |= CS6;
    break;  
  case DataBits7:
    options.c_cflag |= CS7;
    break;  
  case DataBits8:
    options.c_cflag |= CS8;
    break;  
}

  tcsetattr(fd, TCSANOW, &options);
}

void SerialPort::setStopBits(StopBits SB) {}
void SerialPort::setParity(Parity P) {}
